import CustomEvent = WechatMiniprogram.CustomEvent;
import {page, pageFunc} from "../common/PageBuilder";
import {ItemDetailPage} from "../common/pages/ItemDetailPage";
import {Task, TaskType} from "../../modules/taskModule/data/Task";
import {AuthPage} from "../common/partPages/UserPage";
import {UploaderPage} from "../common/partPages/UploaderPage";
import {PickerPage} from "../common/partPages/PickerPage";
import {DatePicker} from "../common/partPages/DatePickerPage";
import {waitForLogin} from "../../modules/userModule/managers/UserManager";
import {waitForDataLoad} from "../../modules/coreModule/managers/DataManager";
import {iLevelRepo, InstructorLevel} from "../../modules/userModule/data/Role";
import {Locations} from "../../utils/Locations";
import {handleError} from "../../modules/coreModule/managers/AlertManager";
import {TaskInterface} from "../../modules/taskModule/TaskCommon";
import {DataLoader, field} from "../../modules/coreModule/data/DataLoader";
import {pageMgr} from "../../modules/coreModule/managers/PageManager";
import {PaymentPage} from "../payment/PaymentPage";
import {BasePageData} from "../common/core/BasePage";
import {Constructor} from "../../utils/BaseContext";
import {RecruitDetailPage} from "../recruitDetail/RecruitDetailPage";
import {TemplateIds} from "../../modules/messageModule/MessageCommon";
import {blockLoading, showLoading} from "../../modules/coreModule/managers/LoadingManager";
import {CoreLoading} from "../../modules/coreModule/CoreCommon";
import {DateUtils} from "../../utils/DateUtils";
import {CloudFileUtils, MediaFile} from "../../utils/CloudFileUtils";

// 修饰input事件函数，进行类型检查，如果需要进行处理，则在被修饰函数中返回处理好的值即可
export function input(field: string,
	type: Constructor<String | Number | Boolean> = String) {
	return (obj, key, desc) => {
		const oriFunc = desc.value;
		desc.value = function (e: CustomEvent<any>) {
			console.log(key, ":", e);
			let value = oriFunc.call(this, e) || e.detail;
			if (typeof value == "object") value = value.value;
			switch (type) {
				case Number:
					value = Number.parseInt(value);
					break;
				case Boolean:
					value = !!value;
					break;
			}
			this.setData({ [field]: value });
		}
	}
}

class Data extends BasePageData {

	@field(Task)
	item: Task
	@field([InstructorLevel])
	levels: InstructorLevel[] = [];
	@field(Number)
	type: TaskType
	@field(Object)
	poster: MediaFile;
}

class Param {
	type: TaskType
}

const TitleArr = ["成长训练营", "场地", "日常兼职", "军事训练"];

const MinStartTimeDiffDays = 1; // 最小开始时间间隔
const MinDurationDays = 1; // 最短任务天数

@page("pubTask", "发布任务")

export class PubTaskPage extends ItemDetailPage<Data, Task, Param> {
	public data = new Data();
	private levelIdx;

	/**
	 * 部分页
	 */
	public userPage: AuthPage = new AuthPage();
	public uploaderPage: UploaderPage = new UploaderPage("task", "task");
	public pickerPage = new PickerPage();
	public datePickerPage: DatePicker = new DatePicker();

	onLoad(e) {
		super.onLoad(e);
		console.log("params", this.params)
		this.setData({
			type: this.params.type,
			title: TitleArr[this.params.type]
		})
		this.loadData().then();
	}

	/**
	 * 数据加载完成回调
	 */
	@waitForLogin
	@waitForDataLoad
	private loadData() {
		const item = new Task();
		item.type = this.params.type = Number(this.params.type);
		// if (this.params.type == TaskType.Reward) {
		// 		item.count = item.minCount = 1;
		// }
		return this.setData({
			item, levels: iLevelRepo().find().filter(l => l.level > 0)
		})
	}

	// region 事件

	// region 数据

	/**
	 * 最早开始时间（MinStartTimeDiffDays天后）
	 */
	public get minStartTime() {
		return Date.now();
		// return DateUtils.date2DayStart(Date.now()).getTime() +
		// 	MinStartTimeDiffDays * DateUtils.Day;
	}

	/**
	 * 最早结束时间（MinStartTimeDiffDays天后）
	 */
	public get minEndTime() {
		const startTime = Math.max(this.minStartTime, this.item.startTime || 0);
		return startTime + 10 * DateUtils.Minute; // MinDurationDays * DateUtils.Day;
	}

	/**
	 * 最早开始时间（MinStartTimeDiffDays天后）
	 */
	public get minSignStartTime() { return Date.now(); }

	/**
	 * 最早开始时间（MinStartTimeDiffDays天后）
	 */
	public get maxSignStartTime() { return this.item.endTime }

	/**
	 * 最早结束时间（MinStartTimeDiffDays天后）
	 */
	public get minSignEndTime() {
		return Math.max(this.minSignStartTime, this.item.signStartTime || 0);
	}

	/**
	 * 最早结束时间（MinStartTimeDiffDays天后）
	 */
	public get maxSignEndTime() {
		return this.item.endTime
	}

	// endregion

	// region 输入事件

	@pageFunc
	public async onLocationTap() {
		const locIdxs = await this.pickerPage.startPicker(
			"选择地点", Locations);
		console.log(locIdxs);
		if (!locIdxs) return;

		const province = Locations[locIdxs[0]];
		const city = province.sub[locIdxs[1]];
		const region = city.sub?.[locIdxs[2]];

		await this.setItemData({
			location: `${province.name} ${city.name} ${region?.name || ""}`
		})
	}

	@pageFunc
	public async onStartDateTap() {
		const startTime = await this.datePickerPage.startPicker(
			"选择开始时间", this.item.startTime, this.minStartTime
		);
		if (!startTime) return;
		await this.setItemData({ startTime });
		if (this.item.type == TaskType.Reward)
			await this.setItemData({ signStartTime: startTime });
	}

	@pageFunc
	public async onEndDateTap() {
		const endTime = await this.datePickerPage.startPicker(
			"选择结束时间", this.item.endTime, this.minEndTime
		);
		if (!endTime) return;
		await this.setItemData({ endTime });
		if (this.item.type == TaskType.Reward)
			await this.setItemData({ signEndTime: endTime });
	}

	@pageFunc
	public async onSignStartDateTap() {
		const signStartTime = await this.datePickerPage.startPicker(
			"选择报名开始时间", this.item.signStartTime,
			this.minSignStartTime, this.maxSignStartTime
		);
		if (!signStartTime) return;
		await this.setItemData({ signStartTime });
	}

	@pageFunc
	public async onSignEndDateTap() {
		const signEndTime = await this.datePickerPage.startPicker(
			"选择报名截止时间", this.item.signEndTime,
			this.minSignEndTime, this.maxSignEndTime
		);
		if (!signEndTime) return;
		await this.setItemData({ signEndTime });
	}

	public get levelTexts() {
		return this.data.levels.map(l => ({ name: l.name }));
	}

	@pageFunc
	public async onLevelTap() {
		this.levelIdx = await this.pickerPage.startPicker(
			"选择等级", this.levelTexts, this.levelIdx);
		if (!this.levelIdx) return;
		await this.setItemData({
			level: this.data.levels[this.levelIdx[0]].level
		});
	}

	@pageFunc
	@input('item.title')
	public onTitleInput(e: CustomEvent) { }

	@pageFunc
	@input('item.count', Number)
	public onCountInput(e: CustomEvent) {
		// return Math.max(this.item.minCount, Number(e.detail))
	}

	@pageFunc
	@input('item.minCount', Number)
	public onMinCountInput(e: CustomEvent) {
		// return Math.min(this.item.count, Number(e.detail))
	}

	@pageFunc
	@input('item.salary', Number)
	public onSalaryInput(e: CustomEvent) {
		return Number(e.detail) * 100;
	}

	@pageFunc
	@input('item.note')
	public onNoteInput(e: CustomEvent) { }

	@pageFunc
	@input('item.phone')
	public onPhoneInput(e: CustomEvent) { }

	@pageFunc
	@input('item.name')
	public onNameInput(e: CustomEvent) { }

	@pageFunc
	public async onPosterChoose(e: CustomEvent) {
		await this.setData({poster: e.detail.file});
	}

	@pageFunc
	public async onPosterDelete(e: CustomEvent) {
		await this.setData({poster: null});
	}

	public async uploadPoster():Promise<any> {
		if(this.data.poster){
			const file =  CloudFileUtils.mediaFile2File("task", this.data.poster);
			return (await CloudFileUtils.uploadFile(file, "task")).fileID;
		}
	}
	// endregion

	@pageFunc
	@handleError
	public submit() {
		this.check();
		wx.requestSubscribeMessage({
			tmplIds: [
				TemplateIds["审核通知"],
				TemplateIds["需求通知"],
				TemplateIds["报名通知"]
			],
			success: this.doSubmit.bind(this)
		})
	}
	@showLoading(CoreLoading.Mask)
	@blockLoading
	@handleError
	private async doSubmit() {
		await this.uploadPictures();
		await this.publishTask();
	}

	/**
	 * 校验内容
	 */
	private check() {
		if (!this.item.title) throw "请输入标题";

		if (!this.item.location) throw "请选择地区";

		if (this.item.startTime > this.item.endTime) throw "开始时间不能大于结束时间";
		if (this.item.signStartTime > this.item.signEndTime) throw "报名开始时间不能大于结束时间";
		if (Math.max(DateUtils.dayDiff(this.item.endTime, this.item.startTime), 1)
			< MinDurationDays) throw "持续时长过短";

		if (!this.item.count) throw "请输入人数";
		if (this.item.count < this.item.minCount) throw "请输入正确的人数范围";

		if (this.item.type != TaskType.Reward) {
			if (!this.item.salary) throw "请输入薪水";
			if (this.item.salary < 100) throw "日薪不得少于一元";
		}
		if(!this.item.name) throw "请填写姓名";

		if (!this.item.phone) throw "请输入联系方式";
		if (!/^1\d{10}$/.test(this.item.phone)) throw "请输入正确的联系方式";

		if (this.item.type == TaskType.Camp &&
			!this.item.level) throw "请选择等级";
	}

	/**
	 * 上传图片
	 */
	private async uploadPictures() {
		const fileIds = await this.uploaderPage.uploadPictures();
		const poster = await this.uploadPoster();
		await this.setItemData({ images: fileIds });
		await this.setItemData({poster});
	}

	/**
	 * 发布任务
	 */
	@showLoading(CoreLoading.Mask)
	@blockLoading
	private async publishTask() {
		let res = await TaskInterface.PublishTask({ task: this.item });
		const task = DataLoader.load(Task, res.task);

		if (task.firstTradeId || task.contractId)
			await pageMgr().change(PaymentPage, <any>{
				tradeId: task.firstTradeId,
				contractId: task.contractId,
				onSuccess: () =>
					pageMgr().change(RecruitDetailPage, { id: task._id })
			})
		else
			pageMgr().change(RecruitDetailPage, { id: task._id }).then();
	}

	// endregion

}
